#ifndef WFTOOLS_H
#define WFTOOLS_H

#include <dirent.h>
#include <vector>
#include <iostream>
#include <fstream>
#include <string>
#include <cstdio>
#include <ctime>
#include <cstring>
#include <algorithm>
#include <sstream>
#include <sys/stat.h>

using std::string ;
using std::endl ;
using std::cout;
using std::vector ;

//2017-11-29
int wft_str2int(std::string ymd)
{
  return (int)(atof(ymd.c_str()));
}

//计算两个日期的间隔天数 2017-12-16
int wft_get_days_between(int ymdsmall, int ymdbig)
{
  int day = ymdsmall % 100;
  int month = (ymdsmall % 10000) / 100;
  int year = ymdsmall / 10000;
  struct tm timesmall;
  memset(&timesmall, 0, sizeof(struct tm));
  timesmall.tm_mday = day;
  timesmall.tm_mon = month - 1;
  timesmall.tm_year = year - 1900;

  int day2 = ymdbig % 100;
  int month2 = (ymdbig % 10000) / 100;
  int year2 = ymdbig / 10000;
  struct tm timebig;
  memset(&timebig, 0, sizeof(struct tm));
  timebig.tm_mday = day2;
  timebig.tm_mon = month2 - 1;
  timebig.tm_year = year2 - 1900;

  time_t tbig = mktime(&timebig);
  time_t tsmall = mktime(&timesmall);
  time_t secs = tbig - tsmall;
  int days = secs / 3600 / 24;
  return days + 1;
}



//2017-11-29
std::string wft_convert_ymd2y_m_d(std::string ymd)
{
  std::string year = ymd.substr(0, 4);
  std::string mon = ymd.substr(4, 2);
  std::string day = ymd.substr(6, 2);
  return year + "-" + mon + "-" + day;
}

//2017-12-07
std::string wft_convert_ymd2y_m_d_hms(std::string ymdhms)
{
  std::string year = ymdhms.substr(0, 4);
  std::string mon = ymdhms.substr(4, 2);
  std::string day = ymdhms.substr(6, 2);
  std::string hour = "00" ;
  std::string minu = "00" ;
  std::string seco = "00" ;
  if( ymdhms.length() >= 10 ) hour = ymdhms.substr(8,2) ;
  if( ymdhms.length() >= 12 ) minu = ymdhms.substr(10,2) ;
  if( ymdhms.length() >= 12 ) seco = ymdhms.substr(12,2) ;
  return year + "-" + mon + "-" + day + " " + hour+":"+minu+":" + seco ;
}

//int to string
std::string wft_int2str(int val)
{
  std::stringstream ss;
  ss << val;
  return ss.str();
}


//2017-11-29
std::string wft_convert_ymdi2y_m_d(int ymd0)
{
  std::string ymd = wft_int2str(ymd0);
  std::string year = ymd.substr(0, 4);
  std::string mon = ymd.substr(4, 2);
  std::string day = ymd.substr(6, 2);
  return year + "-" + mon + "-" + day;
}

//2017-11-29
bool wft_isValidNoaaNdvi( int ndvi , short qaval)
{
  if (ndvi >= -2000 && ndvi <= 10000)
  {
    short mask = 2;//mask out 1,2,3 bit == 1. only get off cloud 2017-12-17 by wyj.
    short maskout = qaval & mask;
    if ( maskout == 0) return true; 
    else return false;
  }else
  {
    return false;
  }
}




//日期反推日期 2017-11-28
int wft_get_ymd_before(int endymd, int nday)
{
  int day = endymd % 100;
  int month = (endymd % 10000) / 100;
  int year = endymd / 10000;
  struct tm time1;
  memset( &time1, 0, sizeof(struct tm));
  time1.tm_mday = day ;
  time1.tm_mon = month  - 1;
  time1.tm_year = year - 1900;

  time_t t1 = mktime(&time1);
  time_t t0 = t1 - nday * 60 * 60 * 24;
  struct tm * time0 = localtime(&t0);
  int day0 = time0->tm_mday;
  int mon0 = time0->tm_mon + 1;
  int year0 = time0->tm_year + 1900;
  return year0 * 10000 + mon0 * 100 + day0;
}


//2018-2-13 计算下一天
int wft_nextday(int ymd0, int nday)
{
  int day = ymd0 % 100;
  int month = (ymd0 % 10000) / 100;
  int year = ymd0 / 10000;
  struct tm time1;
  memset( &time1, 0, sizeof(struct tm));
  time1.tm_mday = day ;
  time1.tm_mon = month  - 1;
  time1.tm_year = year - 1900;

  time_t t1 = mktime(&time1);
  time_t t0 = t1 + nday * 60 * 60 * 24;
  struct tm * time0 = localtime(&t0);
  int day0 = time0->tm_mday;
  int mon0 = time0->tm_mon + 1;
  int year0 = time0->tm_year + 1900;
  return year0 * 10000 + mon0 * 100 + day0;
}


//日期结构体
struct WYmd {
  int year, month, day;
  bool isleapyear;
};



//从字符串数组中找到索引
int wft_get_strindex_from_array(std::string find, std::string array[] , int size)
{
  for (int i = 0; i < size; ++i)
  {
    if (find == array[i])
    {
      return i;
    }
  }
  return -1;
}



//float to string
std::string wft_float2str(float val)
{
  std::stringstream ss;
  ss << val;
  return ss.str();
}
//double to string 2018-2-23
std::string wft_double2str(double val)
{
  char buff[128] ;
  sprintf(buff , "%f" , val ) ;
  return string(buff) ;
}





//获取当前日期int，格式YYYYMMDD
int wft_current_dateymd_int()
{
  time_t theTime = time(NULL);
  //struct tm *aTime = localtime(&theTime);//use utc
  struct tm *aTime = gmtime(&theTime);//modify for utc  2017-10-23.
  int day = aTime->tm_mday;
  int month = aTime->tm_mon + 1;  
  int year = aTime->tm_year + 1900; 
  return year * 10000 + month * 100 + day ;
}

//获取当前日期和时间int，格式YYYYMMDD 2017-10-23
int wft_current_dateymd_int2(int& hhmm)
{
  time_t theTime = time(NULL);
  struct tm *aTime = gmtime(&theTime);
  int day = aTime->tm_mday;
  int month = aTime->tm_mon + 1;
  int year = aTime->tm_year + 1900;

  int hour = aTime->tm_hour;
  int minu = aTime->tm_min;
  hhmm = hour * 100 + minu;

  return year * 10000 + month * 100 + day;
}


//获取当前日期，格式YYYYMMDD HH:mm:ss 2017-11-14
std::string wft_current_datetimestr()
{
  time_t theTime = time(NULL);
  struct tm *aTime = localtime(&theTime);
  int day = aTime->tm_mday;
  int month = aTime->tm_mon + 1;
  int year = aTime->tm_year + 1900;

  int hour = aTime->tm_hour;
  int minu = aTime->tm_min;
  int sec = aTime->tm_sec;

  char buff[30];
  sprintf(buff, "%04d-%02d-%02d %02d:%02d:%02d", year, month, day , hour ,minu , sec );
  return std::string(buff);
}



//获取 日期，格式YYYYMMDD 2017-11-15
std::string wft_ymd_int2str( int ymdi )
{
  int year = ymdi / 10000;
  int mon = (ymdi % 10000) / 100;
  int day = ymdi % 100;

  char buff[30];
  sprintf(buff, "%04d-%02d-%02d", year, mon, day);
  return std::string(buff);
}



//替换字符串
std::string wft_replaceString(std::string str, const std::string& from, const std::string& to) {
  size_t start_pos = 0;
  while ((start_pos = str.find(from, start_pos)) != std::string::npos) {
    str.replace(start_pos, from.length(), to);
    start_pos += to.length(); // Handles case where 'to' is a substring of 'from'
  }
  return str;
}

//获取当前时间
std::string wft_get_current_time() {
  //#include <ctime>
  time_t time0;
  time(&time0);
  return std::string(asctime(localtime(&time0)));
}

//判断文件是否存在
bool wft_test_file_exists(const std::string& name) {
  std::ifstream f(name.c_str());
  return f.good();
}
//获取当前日期，格式YYYYMMDD
std::string wft_current_dateymd()
{
  time_t theTime = time(NULL);
  struct tm *aTime = localtime(&theTime);
  int day = aTime->tm_mday;
  int month = aTime->tm_mon + 1;  
  int year = aTime->tm_year + 1900; 
  char buff[10];
  sprintf(buff, "%04d%02d%02d", year, month, day);
  return std::string(buff);
}

//从路径中截取文件名
std::string wft_base_name(std::string const & path)
{
  return path.substr(path.find_last_of("/\\") + 1);
}




int wft_linux_get_dir_files(std::string dir , std::vector<std::string>& files)
{
  if( *dir.rbegin() != '/' )
  {
      dir += "/" ;
  }
  
  struct dirent * dirp ;
  DIR* dp = opendir(dir.c_str()) ;
  if( dp == NULL )
  {
    std::cout<<"Error : failed to open "<<dir<<std::endl ;
    //comment this 2018-2-11 ;//exit(131) ;
    return 131 ;
  } 
  while( (dirp=readdir(dp)) != NULL )
  {
    
    bool isdir = false ;
    if( dirp->d_type==0 )
    {
        std::string tpath = dir + std::string(dirp->d_name) ;
        DIR* pDir = opendir(tpath.c_str() ) ;
        if( pDir != NULL )
        {
            isdir = true ;
        }
    }

    if( strcmp(dirp->d_name,".") == 0  ){
      continue ;
    }else if( strcmp(dirp->d_name,"..") ==0 )
    {
      continue ;
    }else if( dirp->d_type == 4 || isdir )
    {//sub dir
        std::string subdir = dir + std::string(dirp->d_name) ;
        std::cout<<"find subdir "<<subdir<<std::endl ;
        wft_linux_get_dir_files( subdir , files ) ;
    }else
    {
        std::string filepath = dir + std::string(dirp->d_name) ;
        files.push_back( filepath ) ;
    }
  }
  closedir(dp) ;
  return 0 ;
}

//写入日志
void wft_log(std::string logdir , std::string programid, std::string content)
{
  if( logdir != "" )
  {
  	if (*logdir.rbegin() != '/') {
	  logdir += "/";
	}
  }
  std::string ymd = wft_current_dateymd();
  std::string logfile = logdir + programid + "-" + ymd + ".log" ;
  std::ofstream outfs;
  if (wft_test_file_exists(logfile))
  {
    outfs.open(logfile.c_str(), std::ofstream::app);
  }
  else {
    outfs.open(logfile.c_str());
  }
  std::string currTime = wft_get_current_time();
  outfs << currTime << " -> " << content << std::endl;
  std::cout<<content<<std::endl ;
  outfs.close();

}


//是否闰年
bool wft_is_leapyear(int year)
{
  if (year % 400 == 0)
    return true;
  else if (year % 100 == 0)
    return false;
  else if (year % 4 == 0)
    return true;
  else
    return false;
}

//2017-11-10 年月日转换日序数当年。
int wft_convertymd2dayofyear(int mon, int day, int year)
{
  int days[2][13] = {
    { 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 },
    { 0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 }
  };
  int leap =  (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
  return days[leap][mon] + day;
}
//2017-11-10 日年转换为月份和日
void wft_convertdayofyear2monthday(int year , int dayofyear , int& month , int& day )
{
  month = 0;
  day = 0;
  int days[2][13] = {
    { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 , 367 },
    { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 , 367 }
  };
  int leap = (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
  for (int imon = 1; imon <= 12; ++imon)
  {
    if (dayofyear <= days[leap][imon])
    {
      month = imon;
      day = dayofyear - days[leap][imon - 1];
      return;
    }
  }
  std::cout << "Error: day of year " << dayofyear << " is invalid." << std::endl;
}





//2017-11-09
void wft_get_allfiles( std::string dir , 
  std::vector<std::string>& allfiles )
{
  wft_linux_get_dir_files( dir , allfiles);
}


//2017-11-23
void wft_get_allSelectedFiles(std::string inDir, std::string fnFixPrefix,
  std::string fnFixTail, int fnFixMidLoc, std::string fnFixMidStr,
  std::vector<std::string>& selectedFiles)
{
  std::vector<std::string> allfiles;
  wft_get_allfiles(inDir, allfiles);
  int nfiles = allfiles.size();
  for (int i = 0; i < nfiles; ++i)
  {
    std::string filepath = allfiles[i];
    std::string filename = wft_base_name(filepath);
    int pos0 = filename.find(fnFixPrefix);
    if (pos0 == 0)
    {
      int pos1 = filename.rfind(fnFixTail);
      if (pos1 != std::string::npos && pos1 == filename.length() - fnFixTail.length())
      {
        if (fnFixMidLoc >= 0 && fnFixMidStr != "")
        {
          if( fnFixMidLoc + fnFixMidStr.length() - 1 < filename.length() )
          {
            std::string mid1 = filename.substr(fnFixMidLoc, fnFixMidStr.length());
            if (mid1 == fnFixMidStr)
            {
              selectedFiles.push_back(filepath);
            }
          }
        }
        else {
          selectedFiles.push_back(filepath);
        }
      }
    }
  }
}


//2017-12-29
void wft_get_allSelectedFiles2(std::string inDir, std::string fnFixPrefix,
  std::string fnFixTail, std::string musthas , std::string nothas ,
  std::vector<std::string>& selectedFiles)
{
  std::vector<std::string> allfiles;
  wft_get_allfiles(inDir, allfiles);
  int nfiles = allfiles.size();
  for (int i = 0; i < nfiles; ++i)
  {
    std::string filepath = allfiles[i];
    std::string filename = wft_base_name(filepath);
    int pos0 = filename.find(fnFixPrefix);
    if (pos0 == 0)
    {
      int pos1 = filename.rfind(fnFixTail);
      if (pos1 != std::string::npos && pos1 == filename.length() - fnFixTail.length())
      {
        bool musthasok = true ;
        if( musthas != "" && filename.find(musthas) == std::string::npos )
        {
          musthasok = false ;
        }
        bool nothasok = true ;
        if( nothas != "" && filename.find(nothas) != std::string::npos )
        {
          nothasok = false ;
        }
        if ( musthasok && nothasok )
        {
          selectedFiles.push_back(filepath);
        }
        
      }
    }
  }
}




//从配置文件获取参数 2017-10-25
//read extra params file by key. note the key should like the same as text file write do not use space.
std::string wft_getValueFromExtraParamsFile(std::string extrafile, std::string key , bool musthas=false )
{
  std::string res = "";
  bool find = false;
  std::ifstream  ifs(extrafile.c_str());
  while (getline(ifs, res)) {
      if( res.length() > 0 )//bugfixed 2017-10-25.
      {
          if ((int)res[res.length() - 1] == 0 || (int)res[res.length() - 1] == 13)
          {
              res = res.substr(0, res.length() - 1);
          }
          if (res == key) {
              getline(ifs, res);
              if( res.length() > 0 )//bugfixed 2017-11-10
              {
                if ((int)res[res.length() - 1] == 0 || (int)res[res.length() - 1] == 13)
                {
                  res = res.substr(0, res.length() - 1);
                }
              }
              find = true;
              break;
          }
      }
  }
  ifs.close();
  if (find == false )
  {
    res = "" ;//bugfixed 2017-10-27
    std::cout << "Warning : Not found any params with key : " << key << std::endl;
    if (musthas)
    {
      std::cout << "Error : can not find params of "<<key<<", the program can not run. outing...  " << std::endl;
      exit(111);
    }
  }
  return res;
}


//从配置文件获取参数，增加默认值 2017-11-09
bool wft_has_param2(int argc, char** argv, char* key, std::string& value, bool mustWithValue , std::string defaultForNoValue )
{
  value = "";
  for (int i = 0; i < argc; ++i)
  {
    if (strcmp(argv[i], key) == 0) {
      if (i != argc - 1)
      {
        value = std::string(argv[i + 1]);
        return true;
      }
      else {
        if (mustWithValue) {
          std::cout << "Error: can not find value for key :" << key << ". out." << std::endl;
          exit(99);
        }
        return true;
      }
    }
  }
  if (mustWithValue) {
    std::cout << "Error: can not find value for key :" << key << ". out." << std::endl;
    exit(99);
  }
  value = defaultForNoValue;
  return false;
}




//通过标签获取命令行参数
bool wft_has_param(int argc, char** argv, const char* key, std::string& value , bool mustWithValue )
{
  value = "";
  for (int i = 0; i < argc; ++i)
  {
    if (strcmp(argv[i], key) == 0) {
      if (i != argc - 1)
      {
        value = std::string(argv[i + 1]);
        return true;
      }
      else {
        if (mustWithValue) {
          std::cout << "Error: can not find value for key :" << key << ". out." << std::endl;
          exit(99);
        }
        return true;
      }
    }
  }
  if (mustWithValue) {
    std::cout << "Error: can not find value for key :" << key << ". out." << std::endl;
    exit(99);
  }
  return false;
}

//通过标签获取命令行是否有某个tag
bool wft_has_tag(int argc, char** argv, char* key  )
{
  for (int i = 0; i < argc; ++i)
  {
    if (strcmp(argv[i], key) == 0) {
      return true ;
    }
  }
  return false;
}


//进度显示
void wft_term_progress(size_t curr, size_t total)
{
  static size_t term_progress_percent = -1;
  if (curr < total-1)
  {
    size_t newper = curr * 100 / total;
    if (newper != term_progress_percent) {
      term_progress_percent = newper;
      if (term_progress_percent % 10 == 0) {
        std::cout << term_progress_percent;
      }
      else {
        std::cout << ".";
      }
    }
  }
  else{
    if (term_progress_percent != 100) {
      term_progress_percent = 100;
      std::cout << 100 << std::endl;
    }
  }
}




//复制文件并替换掉变量
int wft_create_file_by_template_with_replacement(std::string targetFile, std::string temfile,
  std::vector<std::string> variableVector,
  std::vector<std::string> replaceStrVector)
{
  std::ofstream ofs(targetFile.c_str());
  std::ifstream ifs(temfile.c_str());

  std::string line;
  while (std::getline(ifs, line))
  {
    for (size_t ir = 0; ir < variableVector.size(); ++ir)
    {
      line = wft_replaceString(line, variableVector[ir], replaceStrVector[ir]);
    }
    ofs << line << std::endl;
  }

  ofs.close();
  ifs.close();
  return 100;
}


//从文件列表文件中读取数组
std::vector<std::string> wft_get_filelist_from_file(std::string filepath , std::string prefix , std::string tail )
{
  std::vector<std::string> res;
  std::ifstream tfs(filepath.c_str());
  std::string line;
  while (std::getline(tfs, line))
  {
    if (line.length() > 1)
    {
      std::string tempInDsPath = prefix + line + tail;
      res.push_back(tempInDsPath);
    }
  }
  tfs.close();
  return res;
}

//逐行写入一个文件
void wft_write_file_linebyline(std::string filepath, std::vector<std::string>& vec, std::string prefix, std::string tail)
{
  std::ofstream tfs(filepath.c_str());
  for (size_t i = 0; i < vec.size(); ++ i )
  {
    tfs << prefix << vec[i] <<tail  << std::endl;
  }
  tfs.close();

}

void wft_compare_minmax(double val, double& vmin, double& vmax)
{
  if (val < vmin) vmin = val;
  if (val > vmax) vmax = val;
}

void wft_make_histfile(double vmin, double vmax, double binwid, std::vector<double> vec, std::string outfile)
{
  double tmin = ((int)(vmin / binwid))*binwid;
  double tmax = (1+(int)(vmax / binwid))*binwid;
  int numbin = (tmax - tmin) / binwid;
  if (numbin == 0)
  {
    std::cout << "Warning : the number of bin is zero. no hist file will be generated." << std::endl;
    return;
  }
  double* histArray = new double[numbin];
  for (int i = 0; i < numbin; ++i) histArray[i] = 0;
  for (size_t it = 0; it < vec.size(); ++it)
  {
    int ibin = (vec[it] - tmin) / binwid;
    if (ibin < 0) ibin = 0;
    if (ibin >= numbin) ibin = numbin - 1;
    histArray[ibin] += 1;
  }
  int vsize = (int)vec.size();
  std::ofstream histOfs(outfile.c_str());
  histOfs << "#x h" << std::endl;
  for (int i = 0; i < numbin; ++i)
  {
    histArray[i] = histArray[i] / vsize;
    histOfs << (tmin + i*binwid) << " " << histArray[i] << std::endl;
  }
  histOfs.close();
  delete[] histArray;
}

//ASCII 字符串分割 2017-10-25
std::vector<std::string> wft_string_split(std::string wholeString, std::string sep)
{
  std::vector<std::string> result;

  int pos0 = 0;
  while (pos0 < wholeString.length())
  {
    int pos1 = wholeString.find(sep,pos0);
    if (pos1 == std::string::npos)
    {
      std::string substr = wholeString.substr(pos0);
      if (substr.length() > 0) result.push_back(substr);
      break;
    }
    else {
      int len1 = pos1 - pos0;
      std::string substr = wholeString.substr(pos0 , len1);
      if (substr.length() > 0) result.push_back(substr);
      pos0 = pos1 + 1;
    }
  }
  return result;
}

//ASCII 字符串分割 2017-12-07 保存空字符
std::vector<std::string> wft_string_split2(std::string wholeString, std::string sep)
{
  std::vector<std::string> result;

  int pos0 = 0;
  while (pos0 < wholeString.length())
  {
    int pos1 = wholeString.find(sep,pos0);
    if (pos1 == std::string::npos)
    {
      std::string substr = wholeString.substr(pos0);
      result.push_back(substr);
      break;
    }
    else {
      int len1 = pos1 - pos0;
      std::string substr = wholeString.substr(pos0 , len1);
      result.push_back(substr);
      pos0 = pos1 + 1;
    }
  }
  return result;
}

//find index of string in vector , -1 for not find 2017-10-25
int wft_get_strindex_from_vector(std::string find, std::vector<std::string> vec)
{
  for (int i = 0; i < vec.size(); ++i)
  {
    if (find == vec[i])
    {
      return i;
    }
  }
  return -1;
}

//2017-10-25
bool wft_string_has_tail(std::string str, std::string tail)
{
  if (str.length() >= tail.length())
  {
    std::string tempTail = str.substr(str.length() - tail.length());
    if (tempTail == tail)
    {
      return true;
    }
    else
    {
      return false;
    }
  }
  else {
    return false;
  }
}
//2017-10-25
bool wft_string_has_tails(std::string str, std::vector<std::string>& tailvec)
{
  for (int i = 0; i < tailvec.size(); ++i)
  {
    if (wft_string_has_tail(str, tailvec[i]))
    {
      return true;
    }
  }
  return false;
}


//2017-10-26
int wft_remove_file(std::string filepath)
{
	if (remove(filepath.c_str()) != 0)
	{
		std::cout << "Error deleting file:" << filepath << std::endl;
		return 101;
	}
	else
	{
		std::cout << "Successfully deleting file:" << filepath << std::endl;
		return 0;
	}
}




//2017-12-01
std::string wft_getValueDoubleFromExtraParamsFile(std::string extrafile, std::string key, double& retval, bool musthas = false)
{
  std::string res = wft_getValueFromExtraParamsFile(extrafile, key, musthas);
  if (res == "")
  {
    retval = 0;
  }
  else {
    retval = atof(res.c_str());
  }
  return res;
}

//2017-12-01
std::string wft_getValueIntFromExtraParamsFile(std::string extrafile, std::string key, int& retval, bool musthas = false)
{
  std::string res = wft_getValueFromExtraParamsFile(extrafile, key, musthas);
  if (res == "")
  {
    retval = 0;
  }
  else {
    retval =(int) atof(res.c_str());
  }
  return res;
}

///将yyyymmdd分割三个整形数字数组 //2018-1-6
void wft_sepYmd(int ymd, int* ymdarr)
{
  ymdarr[0] = ymd / 10000;
  ymdarr[1] = (ymd % 10000) / 100;
  ymdarr[2] = ymd % 100;
}
//2018-1-6
void wft_getfivdaysStartEnd(int ymdi, int & ymd0, int& ymd1)
{
  int a[3];
  wft_sepYmd(ymdi, a);
  if (a[2] < 6)
  {
    ymd0 = a[0] * 10000 + a[1] * 100 + 1;
    ymd1 = a[0] * 10000 + a[1] * 100 + 5;
  }
  else if (a[2] < 11)
  {
    ymd0 = a[0] * 10000 + a[1] * 100 + 6;
    ymd1 = a[0] * 10000 + a[1] * 100 + 10;
  }
  else if (a[2] < 16)
  {
    ymd0 = a[0] * 10000 + a[1] * 100 + 11;
    ymd1 = a[0] * 10000 + a[1] * 100 + 15;
  }
  else if (a[2] < 21)
  {
    ymd0 = a[0] * 10000 + a[1] * 100 + 16;
    ymd1 = a[0] * 10000 + a[1] * 100 + 20;
  }
  else if (a[2] < 26)
  {
    ymd0 = a[0] * 10000 + a[1] * 100 + 21;
    ymd1 = a[0] * 10000 + a[1] * 100 + 25;
  }
  else
  {
    ymd0 = a[0] * 10000 + a[1] * 100 + 26;
    if (a[1] == 2)
    {
      if (wft_is_leapyear(a[0]))
      {
        ymd1 = a[0] * 10000 + a[1] * 100 + 29;
      }
      else
      {
        ymd1 = a[0] * 10000 + a[1] * 100 + 28;
      }
    }
    else if (a[1] == 4 || a[1] == 6 || a[1] == 9 || a[1] == 11)
    {
      ymd1 = a[0] * 10000 + a[1] * 100 + 30;
    }
    else
    {
      ymd1 = a[0] * 10000 + a[1] * 100 + 31;
    }
  }
}

//2018-1-6
void wft_gettendaysStartEnd(int ymdi, int & ymd0, int& ymd1)
{
  int a[3];
  wft_sepYmd(ymdi, a);
  if (a[2] < 11)
  {
    ymd0 = a[0] * 10000 + a[1] * 100 + 1;
    ymd1 = a[0] * 10000 + a[1] * 100 + 10;
  }
  else if (a[2] < 21)
  {
    ymd0 = a[0] * 10000 + a[1] * 100 + 11;
    ymd1 = a[0] * 10000 + a[1] * 100 + 20;
  }
  else
  {
    ymd0 = a[0] * 10000 + a[1] * 100 + 21;
    if (a[1] == 2)
    {
      if (wft_is_leapyear(a[0]))
      {
        ymd1 = a[0] * 10000 + a[1] * 100 + 29;
      }
      else
      {
        ymd1 = a[0] * 10000 + a[1] * 100 + 28;
      }
    }
    else if (a[1] == 4 || a[1] == 6 || a[1] == 9 || a[1] == 11)
    {
      ymd1 = a[0] * 10000 + a[1] * 100 + 30;
    }
    else
    {
      ymd1 = a[0] * 10000 + a[1] * 100 + 31;
    }
  }
}
//2018-1-6
void wft_getmonStartEnd(int ymdi, int & ymd0, int& ymd1)
{
  int a[3];
  wft_sepYmd(ymdi, a);
  ymd0 = a[0] * 10000 + a[1] * 100 + 1;
  if (a[1] == 2)
  {
    if (wft_is_leapyear(a[0]))
    {
      ymd1 = a[0] * 10000 + a[1] * 100 + 29;
    }
    else
    {
      ymd1 = a[0] * 10000 + a[1] * 100 + 28;
    }
  }
  else if (a[1] == 4 || a[1] == 6 || a[1] == 9 || a[1] == 11)
  {
    ymd1 = a[0] * 10000 + a[1] * 100 + 30;
  }
  else
  {
    ymd1 = a[0] * 10000 + a[1] * 100 + 31;
  }
}
//2018-1-6
void wft_getseaStartEnd(int ymdi, int & ymd0, int& ymd1)
{
  int a[3];
  wft_sepYmd(ymdi, a);
  if (a[1] < 3)
  {
    ymd0 = (a[0] - 1) * 10000 + 1201;
    ymd1 = a[0] * 10000 + 229;
    if (wft_is_leapyear(a[0]))
    {
      ymd1 = a[0] * 10000 + 229;
    }
    else
    {
      ymd1 = a[0] * 10000 + 228;
    }
  }
  else if (a[1] < 6)
  {
    ymd0 = a[0] * 10000 + 301;
    ymd1 = a[0] * 10000 + 531;
  }
  else if (a[1] < 9)
  {
    ymd0 = a[0] * 10000 + 601;
    ymd1 = a[0] * 10000 + 831;
  }
  else if (a[1] < 12)
  {
    ymd0 = a[0] * 10000 + 901;
    ymd1 = a[0] * 10000 + 1130;
  }
  else {
    ymd0 = a[0] * 10000 + 1201;
    if (wft_is_leapyear(a[0] + 1))
    {
      ymd1 = (a[0] + 1) * 10000 + 229;
    }
    else
    {
      ymd1 = (a[0] + 1) * 10000 + 228;
    }
  }
}
//2018-1-6
void wft_getyeaStartEnd(int ymdi, int & ymd0, int& ymd1)
{
  int a[3];
  wft_sepYmd(ymdi, a);
  ymd0 = a[0] * 10000 + 101;
  ymd1 = a[0] * 10000 + 1231;
}



//2018-1-12
void wft_mkdir(std::string dir)
{
#if defined(_WIN32)
  _mkdir(dir.c_str());
#else
  mkdir(dir.c_str(),0777);
#endif 
}


//2018-1-12
std::string wft_int2str2(int val, int wid)
{
  char carr[10] = { '0','1','2','3','4','5','6','7','8','9' };
  char buff[32];
  char fmt[10];
  fmt[0] = '%';
  fmt[1] = '0';
  fmt[2] = carr[wid];
  fmt[3] = 'd';
  fmt[4] = '\0';
  sprintf(buff, fmt, val);
  return std::string(buff);
}

//2018-1-12
//根据日期和格式生成路径
std::string wft_getDirByDirFmt(std::string rootdir, std::string fmt, int ymd)
{
  if (rootdir.length() == 0) return "";
  if (*(rootdir.end() - 1) != '/')
  {
    rootdir += "/";
  }
  std::string fulldir = rootdir;
  std::vector<std::string> fmtvec;
  fmtvec = wft_string_split(fmt, "/");
  int year = ymd / 10000;
  int mon = (ymd % 10000) / 100;
  int day = ymd % 100;
  for (int im = 0; im < fmtvec.size(); ++im)
  {
    if (fmtvec[im].find("yyyy") != std::string::npos)
    {
      fulldir += wft_int2str(year);
    }
    if (fmtvec[im].find("mm") != std::string::npos)
    {
      fulldir += wft_int2str2(mon, 2);
    }
    if (fmtvec[im].find("dd") != std::string::npos)
    {
      fulldir += wft_int2str2(day, 2);
    }
    fulldir += "/";
  }
  return fulldir;
}

///2018-1-12 创建输出路径 /outrootdir/     /outrootdir/yyyy/   /outrootdir/yyyymm/     /outrootdir/yyyymmdd/   /outrootdir/yyyy/mm/    /outrootdir/yyyy/mm/dd/
///fmt yyyy yyyymm yyyymmdd yyyy/mm yyyy/mm/dd
std::string wft_makeoutpath(std::string outdir, std::string outname, std::string fmt = "")
{
  if (outdir.length() == 0)
  {
    return outname;
  }
  if (*(outdir.end() - 1) != '/')
  {
    outdir += "/";
  }

  int pos = -1;
  int numnum = 0;
  for (int i = 0; i < outname.length(); ++i)
  {
    if (outname[i] >= '0' && outname[i] <= '9')
    {
      if (pos == -1)
      {
        pos = i;
        numnum = 1 ;
      }
      else
      {
        numnum += 1;
        if (numnum >= 8) break;
      }
    }
    else
    {
      pos = -1;
      numnum = 0;
    }
  }

  if (pos >= 0 && numnum >= 8)
  {
    std::string ymdstr = outname.substr(pos, 8);
    int ymd = wft_str2int(ymdstr);
    int year = ymd / 10000;
    int mon = (ymd % 10000) / 100;
    int day = ymd % 100;

    std::vector<std::string> fmtvec;
    fmtvec = wft_string_split(fmt, "/");
    std::string outdir1 = outdir;
    for (int im = 0; im < fmtvec.size(); ++im)
    {
      if (fmtvec[im].find("yyyy") != std::string::npos)
      {
        outdir1 += wft_int2str(year);
      }
      if (fmtvec[im].find("mm") != std::string::npos)
      {
        outdir1 += wft_int2str2(mon,2);
      }
      if (fmtvec[im].find("dd") != std::string::npos)
      {
        outdir1 += wft_int2str2(day,2);
      }
      outdir1 += "/";
      wft_mkdir(outdir1);
    }
    return outdir1 + outname;

  }
  else
  {
    return outdir + outname;
  }
}



//2018-1-17 night
std::string wft_changetail( std::string str ,std::string oldtail , std::string newtail )
{
    size_t pos = str.rfind( oldtail ) ;
    if( pos == std::string::npos )
    {
      std::cout<<"warning no tail(" + oldtail+") is found."<<std::endl ;
      return str + newtail ;
    }else
    {
      std::string newstr = str.substr(0 , pos ) ;
      return newstr + newtail ;
    }
}


//2018-1-27
std::string wft_extractFirstDateTimeStrFromFilename(std::string filename, int dtlen=8 , std::string noval = "")
{
  int numnum = 0;
  int pos = -1;
  for (int i = 0; i < filename.length(); ++i)
  {
    if (filename[i] >= '0' && filename[i] <= '9')
    {
      if (pos == -1)
      {
        pos = i;
        numnum = 1;
      }
      else
      {
        numnum += 1;
        if (numnum >= dtlen ) break;
      }
    }
    else
    {
      pos = -1;
      numnum = 0;
    }
  }
  if (pos == -1)
  {
    return noval;
  }
  else
  {
    if (numnum >= dtlen)
    {
      return filename.substr(pos, dtlen);
    }
    else
    {
      std::string str1 = filename.substr(pos, numnum);
      for (int inum = numnum; inum <= dtlen; ++inum)
      {
        str1 += "0";
      }
      return str1;
    }
  }
}


//2018-1-28
struct wftVecPair
{
  std::vector<std::string> vec0, vec1;
  void pushpair(std::string v0, std::string v1);
  void pushpair(std::string v0, int v1);
};
void wftVecPair::pushpair(std::string v0, std::string v1)
{
  std::string v0_1 = "{{{" + v0 + "}}}";
  vec0.push_back(v0_1);
  vec1.push_back(v1);
}
void wftVecPair::pushpair(std::string v0, int v1)
{
  std::string v1str = wft_int2str(v1);
  pushpair(v0, v1str);
}



//2018-1-30
std::string wft_makeoutdir(std::string outdir, int yyyymmdd , std::string fmt = "")
{
	if (outdir.length() == 0)
	{
		return "";
	}
	if (*(outdir.end() - 1) != '/')
	{
		outdir += "/";
	}
	int ymd = yyyymmdd ;
	int year = ymd / 10000;
	int mon = (ymd % 10000) / 100;
	int day = ymd % 100;

	std::vector<std::string> fmtvec;
	fmtvec = wft_string_split(fmt, "/");
	std::string outdir1 = outdir;
	for (int im = 0; im < fmtvec.size(); ++im)
	{
		if (fmtvec[im].find("yyyy") != std::string::npos)
		{
			outdir1 += wft_int2str(year);
		}
		if (fmtvec[im].find("mm") != std::string::npos)
		{
			outdir1 += wft_int2str2(mon, 2);
		}
		if (fmtvec[im].find("dd") != std::string::npos)
		{
			outdir1 += wft_int2str2(day, 2);
		}
		outdir1 += "/";
		wft_mkdir(outdir1);
	}
	return outdir1 ;

}




//2018-2-8 sort string vector from big to small
bool wft_descStrComp( const std::string& lstr , const std::string& rstr )
{
  return lstr > rstr ;
}
//2018-2-8 sort string vector from big to small
void wft_descSortStrVec( std::vector<std::string>& vec )
{
  //2018-1-31
  std::cout<<"desc sorting..."<<std::endl ;
  sort( vec.begin() , vec.end() , wft_descStrComp ) ;
  std::cout<<"sort done."<<std::endl ;
}





//2018-2-11 YYYYDDD -> YYYYMMDD
int wft_convertymd7toymd8(int ymd7)
{
  int year = ymd7/1000 ;
  int jday = ymd7%1000 ;
  int month = 0;
  int day = 0;
  int days[2][13] = {
    { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 , 367 },
    { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 , 367 }
  };
  int leap = (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
  for (int imon = 1; imon <= 12; ++imon)
  {
    if (jday <= days[leap][imon])
    {
      month = imon;
      day = jday - days[leap][imon - 1];
      int ymd8 = year * 10000 + month * 100 + day  ;
      return ymd8;
    }
  }
  std::cout << "Error: day of year " << ymd7 << " is invalid." << std::endl;
  return 10000101 ;
}


//2018-2-13 获取时间段缺少文件信息，大于3个是省略后面的
std::string wft_get_lostfile( std::vector<std::string>& files , int ymd0 , int ymd1 )
{
    std::vector<int> ymdvec ;
    for(int i= 0 ; i<files.size() ; ++ i )
    {
        std::string filename = wft_base_name(files[i]) ;
        std::string ymdstr = wft_extractFirstDateTimeStrFromFilename( filename , 8 , "00000000" ) ;
        int ymdi = wft_str2int(ymdstr) ;
        if( ymdi != 0 )
        {
            ymdvec.push_back(ymdi) ;
        }
    }

    if( ymd0 > ymd1 )
    {
        std::cout<<"Error: ymd0 > ymd1 "<<ymd0<<">"<<ymd1<<std::endl ;
        ymd1 = ymd0 ;
    } 

    std::string lostlist = "" ;
    int nlost = 0 ;

    int cymd = ymd0 ;
    while( cymd <= ymd1 )
    {
        bool found = false ;
        for(int i = 0 ; i<ymdvec.size() ; ++ i )
        {
            if( ymdvec[i] == cymd )
            {
               found = true ;
               break ;
            }
        }
        if( found == false )
        {
            ++ nlost ;
            if( nlost <= 3 )
            {
                if( lostlist.length()>0 )
                {
                    lostlist += "," + wft_int2str(cymd)  ;//2018-2-22
                }else
                {
                    lostlist = wft_int2str(cymd)  ;
                }
            }
            
        }
        cymd = wft_nextday( cymd , 1 ) ;
    }

    if( nlost > 3 )
    {
        int others = nlost -3 ;
        lostlist += std::string(", and other ") + wft_int2str(others) + " data." ;
    }
    return lostlist ;
}


/// test if directory is exist
bool wft_direxist( std::string dir )
{
    struct stat info ;
    if( stat(dir.c_str() , &info) != 0 )
    {
        return false ;
    }else if( info.st_mode & S_IFDIR )
    {
        return true ;
    }else
    {
        return false ;
    }
}



//2018-4-12
struct wft_DateRange
{
  int ymd0 , ymd1 ;
} ;


//2018-4-12
//将日期范围分割为自然年，自然季节，自然月，自然旬，自然候，和单个天
void wft_splitYmdRange( 
  int ymd0 , int ymd1 , 
  std::vector<int>& yvec ,
  std::vector<int>& svec ,
  std::vector<int>& mvec ,
  std::vector<int>& tvec ,
  std::vector<int>& fvec , 
  std::vector<int>& dvec  )
{
  int year0 = ymd0 / 10000 ;
  int year1 = ymd1 / 10000 ;
  int mon0 = (ymd0%10000)/100 ;
  int mon1 = (ymd1%10000)/100 ;
  int day0 = ymd0%100 ;
  int day1 = ymd1%100 ;

  std::vector<wft_DateRange> drVec ;

  //划分年
  int dyear = year1 - year0 ;
  if( dyear >= 1 )
  {
    if( mon0 == 1 && day0==1 )
    {
      yvec.push_back(ymd0) ;
    }else
    {
      wft_DateRange dr ;
      dr.ymd0 = ymd0 ;
      dr.ymd1 = year0*10000 + 1231 ;
      drVec.push_back(dr) ;
    }
    for(int iyear = year0+1 ; iyear < year1 ; ++ iyear )
    {
      yvec.push_back(iyear*10000+101) ;
    }
    if( mon1 == 12 && day1==31 )
    {
      yvec.push_back( year1 * 10000 + 101 ) ;
    }else
    {
      wft_DateRange dr ;
      dr.ymd0 = year1 * 10000 + 101  ;
      dr.ymd1 = ymd1 ;
      drVec.push_back(dr) ;
    }
  }else if( dyear == 0 )
  {
    if( mon0 == 1 && day0==1 && mon1==12 && day1==31 )
    {
      yvec.push_back(ymd0) ;
    }else
    {
      wft_DateRange dr ;
      dr.ymd0 = ymd0  ;
      dr.ymd1 = ymd1 ;
      drVec.push_back(dr) ;
    }
  }

  //拆分季节
  std::vector<wft_DateRange> drVec0 ;
  for( int idr = 0 ; idr < drVec.size() ; ++ idr )
  {
    wft_DateRange d = drVec[idr] ;
    int tyear = d.ymd0 / 10000 ;
    int dmon0 = (d.ymd0%10000)/100 ;
    int dmon1 = (d.ymd1%10000)/100 ;

    int mondaycnt[12] = {0,0,0,0, 0,0,0,0, 0,0,0,0 } ;
    int cnt[12] = {0,0,0,0,   0,0,0,0,   0,0,0,0} ;
    for(int im = 1 ; im<=12 ; ++im )
    {
      int imonday0 , imonday1 ;
      wft_getmonStartEnd( tyear*10000 + im*100 + 1 , imonday0 , imonday1 ) ;
      mondaycnt[im-1] = imonday1-imonday0 + 1 ;
      for(int iday = imonday0 ; iday <= imonday1 ; ++ iday )
      {
        if( iday >= d.ymd0 && iday <= d.ymd1 )
        {
          ++ cnt[im-1];
        }
      }
    }
    if( cnt[2]+cnt[3]+cnt[4] == mondaycnt[2]+mondaycnt[3]+mondaycnt[4] )
    {
      svec.push_back( tyear*10000 + 301 ) ;
      cnt[2]=0; cnt[3]=0; cnt[4]=0 ;
    }
    if( cnt[5]+cnt[6]+cnt[7] == mondaycnt[5]+mondaycnt[6]+mondaycnt[7] )
    {
      svec.push_back( tyear*10000 + 601 ) ;
      cnt[5]=0; cnt[6]=0; cnt[7]=0 ;
    }
    if( cnt[8]+cnt[9]+cnt[10] == mondaycnt[8]+mondaycnt[9]+mondaycnt[10] )
    {
      svec.push_back( tyear*10000 + 901 ) ;
      cnt[8]=0; cnt[9]=0; cnt[10]=0 ;
    }
    for(int im = 0 ; im<12 ; ++im )
    {
      if( cnt[im] == mondaycnt[im] )
      {
        mvec.push_back( tyear*10000 + (im+1)*100 + 1 ) ;
      }else if( cnt[im] > 0 )
      {
        int imonday0 , imonday1 ;
        wft_getmonStartEnd( tyear*10000 + (im+1)*100 + 1 , imonday0 , imonday1 ) ;
        if( im + 1 == dmon0 )
        {
          wft_DateRange dr ;
          dr.ymd0 = d.ymd0  ;
          if( im+1 == dmon1 )
          {
            dr.ymd1 = ymd1 ;
          }else
          {
            dr.ymd1 = tyear*10000 + (im+1)*100 + mondaycnt[im] ;
          }
          drVec0.push_back(dr) ;
        }else if( im+1 == dmon1 )
        {
          wft_DateRange dr ;
          dr.ymd0 = tyear*10000 + (im+1)*100 + 1  ;
          dr.ymd1 = ymd1 ;
          drVec0.push_back(dr) ;
        }
      }
    }
  }


  //拆分月
  std::vector<wft_DateRange> drVec1 ;
  for( int idr = 0 ; idr < drVec0.size() ; ++ idr )
  {
    wft_DateRange d = drVec0[idr] ;
    int tyear =d.ymd0 / 10000 ;
    int mon00 = (d.ymd0%10000)/100 ;
    int day00 = d.ymd0%100 ;
    int mon11 = (d.ymd1%10000)/100 ;
    int day11 = d.ymd1%100 ;

    int symd00 , symd11 ;
    wft_getmonStartEnd( d.ymd0 , symd00 , symd11 ) ;

    int dmon = mon11 - mon00 ;
    if( dmon >= 1 )
    {
      if( day00 == 1 )
      {
        mvec.push_back(d.ymd0) ;
      }else
      {
        wft_DateRange dr ;
        dr.ymd0 = d.ymd0  ;
        dr.ymd1 = symd11 ;
        drVec1.push_back(dr) ;
      }
      for( int imon = mon00 + 1 ; imon < mon11 ; ++ imon )
      {
        mvec.push_back( tyear * 10000 + imon*100 + 1 ) ;
      }

      int symd00_1 , symd11_1 ;
      wft_getmonStartEnd( d.ymd1 , symd00_1 , symd11_1 ) ;
      if( d.ymd1 == symd11_1 )
      {
        mvec.push_back( tyear * 10000 + mon11*100 + 1 ) ;
      }else
      {
        wft_DateRange dr ;
        dr.ymd0 = symd00_1 ;
        dr.ymd1 = d.ymd1 ;
        drVec1.push_back(dr) ;
      }
    }else if( dmon== 0 )
    {
      if( symd00 == d.ymd0 
        && symd11 == d.ymd1 )
      {
        mvec.push_back(d.ymd0) ;
      }else
      {
        drVec1.push_back(d) ;
      }
    }
  }

  //拆分十天 五天
  for( int idr = 0 ; idr < drVec1.size() ; ++ idr )
  {
    wft_DateRange d = drVec1[idr] ;
    int tyear = d.ymd0 / 10000 ;
    int tmon = (d.ymd0%10000)/100 ;
    int day00 = d.ymd0%100 ;
    int day11 = d.ymd1%100 ;

    int monstart , monend ;
    int tenstart , tenend ;
    wft_getmonStartEnd( d.ymd0 , monstart , monend ) ;
    int mondayend = monend%100 ;

    int fivarr[6] = {0,0,0, 0,0,0} ;

    for( int iday = 1 ; iday <= monend ; ++ iday  )
    {
      if( iday >= day00 && iday <= day11 )
      {
        int ifiv = (iday-1)/5 ;
        if( ifiv > 5 ) ifiv = 5 ;
        ++ fivarr[ifiv] ;
      }
    }

    if( fivarr[0] + fivarr[1] == 10 )
    {
      tvec.push_back( tyear * 10000 + tmon*100 + 1 ) ;
      fivarr[0] = 0;
      fivarr[1] = 0 ;
    }
    if( fivarr[2] + fivarr[3] == 10 )
    {
      tvec.push_back( tyear * 10000 + tmon*100 + 11 ) ;
      fivarr[2] = 0;
      fivarr[3] = 0 ;
    }
    if( fivarr[4] + fivarr[5] == mondayend - 21 + 1 )
    {
      tvec.push_back( tyear * 10000 + tmon*100 + 21 ) ;
      fivarr[4] = 0;
      fivarr[5] = 0 ;
    }
    int fivcntArr[6] = {5,5,5,5,5,mondayend-26+1} ;
    int fivEndArr[6] = {5,10,15,20,25,mondayend} ;
    for(int i = 0 ; i<6 ; ++ i )
    {
      int ymd_0 = tyear*10000 + tmon*100 + i*5 + 1 ;
      if( fivarr[i] == fivcntArr[i] )
      {
        fvec.push_back(ymd_0) ;
      }else if( fivarr[i] > 0 )
      {
        int ymd_1 = tyear*10000 + tmon*100 + fivEndArr[i] ;
        for( int j = ymd_0 ; j <= ymd_1 ; ++ j )
        {
          if( j >= d.ymd0 && j<= d.ymd1 )
          {
            dvec.push_back(j) ;
          }
        }
      }
    }
  }
}

//2018-4-18日期分割
struct wft_SplitedYmds
{
  vector<int> yvec,svec,mvec,tvec,fvec,dvec ;
};

//2018-4-18
struct wft_DataFileInfo
{
  string dir ;
  string fmt ;
  string prefix,tail ;
} ;

struct wft_DataFileInfoGroup
{
  string code ;
  wft_DataFileInfo arrsix[6] ;//day,fiv,ten,mon,sea,yea
} ;

//2018-4-18
void wft_getSplitedYmdsFiles(int ymd0,int ymd1,
  wft_DataFileInfoGroup& dfGroup,
  vector<string>& haveVec , 
  string& needStr , 
  string& haveStr , 
  string& lostStr
  )
{
    needStr = "Need:" ;
    haveStr = "Have:" ;
    lostStr = "Lost:" ;
    vector<int> yvec,svec,mvec,tvec,fvec,dvec ;
    wft_splitYmdRange( 
      ymd0,ymd1,
      yvec ,
      svec ,
      mvec ,
      tvec ,
      fvec , 
      dvec  ) ;
    string dtype[6] = {"day","five-days","ten-days","month","season","year"};
    for( int i = 0 ; i<6 ; ++ i )
    {
        vector<int> vec1 = dvec ;
        if( i==1 ) vec1 = fvec ;
        else if( i==2 ) vec1 = tvec ;
        else if( i==3 ) vec1 = mvec ;
        else if( i==4 ) vec1 = svec ;
        else if( i==5 ) vec1 = yvec ;

        wft_DataFileInfo& dfi = dfGroup.arrsix[i] ;
        needStr += dtype[i] + ":" ;
        haveStr += dtype[i] + ":" ;
        lostStr += dtype[i] + ":" ;
        for( int j = 0 ; j<vec1.size() ; ++ j )
        {
            string ymdstr = wft_int2str(vec1[j]) ;
            needStr +=  ymdstr + "," ;

            //是否存在文件
            if( dfi.dir != "" )
            {
                string name1 = dfi.prefix + ymdstr + dfi.tail ;
                string path1 = wft_makeoutpath( dfi.dir , name1 ,  dfi.fmt ) ;
                if( wft_test_file_exists(path1) )
                {
                    haveStr += ymdstr + "," ;
                    haveVec.push_back(path1) ;
                }else
                {
                    lostStr += ymdstr + "," ;
                }
            }else
            {
                lostStr += ymdstr + "," ;
            }
        }
        needStr += "; " ;
        haveStr += "; " ;
        lostStr += "; " ;
    }
}

//2018-6-5 path1 is xxx.tif ,
// this function auto create a xxx.tif.cmbnum.txt file
void wft_write_combnumfile( string path1 , int num )
{//outpath.comb_1.txt
  string txtpath = path1 + ".cmbnum.txt" ;
  FILE* pf = fopen( txtpath.c_str() , "w" ) ;
  if( pf == 0 )
  {
      cout<<"Error: failed to create file "<<txtpath<<endl ;
  }else
  {
      fprintf(pf, "%d", num );
      fclose(pf) ;
  }
}

//2018-6-5 path1 is xxx.tif
// this function auto read a xxx.tif.cmbnum.txt file.
int wft_read_combnumfile( string path1 )
{//outpath.comb_1.txt
  string txtpath = path1 + ".cmbnum.txt" ;
  FILE* pf = fopen( txtpath.c_str() , "r" ) ;
  if( pf == 0 )
  {
      return 0 ;
  }else
  {
      int num = 0 ;
      fscanf(pf, "%d", &num );
      fclose(pf) ;
      return num ;
  }
}

//2018-6-5 vec is xxx.tif,xxx.tif...
// this function auto read a xxx.tif.cmbnum.txt file.
int wft_sum_combnumfile( vector<string>& vec )
{//outpath.comb_1.txt
  int sum = 0 ;
  for(int i = 0 ; i<vec.size() ; ++ i )
  {
      string path1 = vec[i] ;
      string txtpath = path1 + ".cmbnum.txt" ;
      FILE* pf = fopen( txtpath.c_str() , "r" ) ;
      if( pf == 0 )
      {
          sum += 1;
      }else
      {
          int num = 0 ;
          fscanf(pf, "%d", &num );
          fclose(pf) ;
          sum += num ;
      }
  }
  return sum ;
}


#endif
